// 获取元素类型
pub fn type_of_val<T: ?Sized>(_: &T) -> &str {
    std::any::type_name::<T>()
}
#[allow(non_snake_case)]
#[macro_export]
macro_rules! Fprintln {
    // The pattern for a single `e`
    () =>{
      println!()
    };
    ($val:expr $(,)?) => {
        // Use of `match` here is intentional because it affects the lifetimes
        // of temporaries - https://stackoverflow.com/a/48732525/1063961
        match &$val {
            tmp => {
                println!("{} = {:#?}", stringify!($val), tmp);
                tmp
            }
        }
    };
    ($($val:expr),+ $(,)?) => {
        ($(Fprintln!($val)),+,)
    };

}

#[allow(non_snake_case)]
#[macro_export]
macro_rules! DBG {
    // NOTE: We cannot use `concat!` to make a static string as a format argument
    // of `eprintln!` because `file!` could contain a `{` or
    // `$val` expression could be a block (`{ .. }`), in which case the `eprintln!`
    // will be malformed.
    () => {
        $crate::eprintln!("{}:{}", file!(), line!())
    };
    ($val:expr ) => {
        match &$val {
             tmp => {
                eprintln!("{}:{} {} = {:#?} ( {} )",
                file!(), line!(), stringify!($val), tmp, $crate::macros_func::type_of_val(tmp));
                tmp
            }
        }
    };
    ($($val:expr),+ $(,)?) => {
        ($($crate::DBG!($val)),+,)
    };
}

pub fn testFn() {
    println!("do called");
}
